package cn.yangtianxia.basic.service.Impl;

import cn.yangtianxia.basic.constant.BaseConstants;
import cn.yangtianxia.basic.dto.RegisterDto;
import cn.yangtianxia.basic.exception.BusinessException;
import cn.yangtianxia.basic.service.IVerifyCodeService;
import cn.yangtianxia.basic.util.StrUtils;
import cn.yangtianxia.basic.util.VerifyCodeUtils;
import cn.yangtianxia.user.domain.User;
import cn.yangtianxia.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String graph(String key) {
        //判断直接跳过图片验证
        if(!StringUtils.hasLength(key)){
            throw  new BusinessException("请输入key");
        }
        //生成随机码
        //String code = VerifyCodeUtils.generateVerifyCode(4);
        String code = StrUtils.getComplexRandomString(4);
        //存放redis里面
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //把随机码转换成base64的图片的string
        return VerifyCodeUtils.VerifyCode(110,35,code);
    }


    /*1.校验参数
        。空校验
        。校验手机号是否已经被注册 ?
                2.图形验证码校验，根据imageCodeKey 从redis获取图形验证码
        2.1 没有拿到 图形验证码失效，报错
        2.2 拿到了，判断输入的图形验证码是否正确

        3.校验验证码是否已经发送过
        3.1 根据手机号拼接业务键，从redis获取短信验证码 key  register:159824985856
        3.1.1 获取不到 说明已经过期，直接生成新的验证码
        3.1.2 获取到了，判断是否过了重发时间1分钟 value 9527:465468426546521
        。小于一分钟，报错：请勿重复获取验证码
        。大于一分钟，使用原来的验证码，刷新过期时间
        4.生成验证码
        5.保存reids 设置过期时间3分钟
        6.发送短信验证码*/

    @Override
    public void smsCode(RegisterDto dto) {
        String type = dto.getType();
        if("register".equals(type)){
            sendRegisterCode(dto);
        }else{//发送绑定验证码
            sendBinderCode(dto);
        }
    }


    /**
     * 真正的发送验证码
     */
    private void sendSmsCode(String businessKey){
        String phone = businessKey.split(":")[1];
        String smsCodeKey = businessKey;
        Object smsCodeTmp = redisTemplate.opsForValue().get(smsCodeKey);//value
        String smsCode = "";
        if(smsCodeTmp != null){
            Long oldTime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);
            if(System.currentTimeMillis()-oldTime <= 1*60*1000){
                throw new BusinessException("请不要恶意调用接口");
            }
            smsCode = smsCodeTmp.toString().split(":")[0];
        }else{
            smsCode = StrUtils.getComplexRandomString(4);
        }
        //5.保存reids 设置过期时间3分钟
        String smsCodeValue = smsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(
                smsCodeKey,
                smsCodeValue,
                3,
                TimeUnit.MINUTES
        );
        //6.发送短信验证码
//        SmsUtils.sendMsg(phone,"您的验证码是：" + smsCode + "。请在3分钟内使用");
        System.out.println("亲，您的验证码是：" + smsCode + "。请在3分钟内使用！！");
    }
    
    /**
     * 发送绑定
     * @param dto
     */
    public void sendBinderCode(RegisterDto dto) {
        String businessKey = BaseConstants.VerifyCodeConstants.BUSINESS_BINDER_PREFIX+dto.getPhone();
        sendSmsCode(businessKey);
    }

    /**
     * 发送注册
     * @param dto
     */
    public void sendRegisterCode(RegisterDto dto) {
        String email = dto.getEmail();
        String phone = dto.getPhone();
        String imageCodeKey = dto.getImageCodeKey();
        String imageCodeValue = dto.getImageCodeValue();
        String smsCode = "";
        if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(imageCodeKey) || StringUtils.isEmpty(imageCodeValue)){
            throw new BusinessException("请填写参数");
        }
        //校验手机号是否已经被注册 ?
        User userp = userMapper.loadByPhone(phone);
        User usere = userMapper.loadByEmail(email);
        if (userp != null || usere != null){
            throw new BusinessException("用户已存在请直接登录");
        }
        //根据图形验证码的key查询redis中的值
        Object imageCodeValueTmp = redisTemplate.opsForValue().get(imageCodeKey);
        if (imageCodeValueTmp == null){
            throw  new BusinessException("图形验证码已经失效请点击重写获取");
        }
        if (!imageCodeValueTmp.toString().equalsIgnoreCase(imageCodeValue)){
            throw  new BusinessException("请填写正确的图形验证码值");
        }
        String businessKey = BaseConstants.VerifyCodeConstants.BUSINESS_REGISTER_PREFIX + phone;
        sendSmsCode(businessKey);
    }




    /**
     * 邮件图片验证
     * @param dto
     */

    @Override
    public void smCode(RegisterDto dto) {
        String email = dto.getEmail();
        String phone = dto.getPhone();
        String imageCodeKey = dto.getImageCodeKey();
        String imageCodeValue = dto.getImageCodeValue();
        String smCode = "";
        if(StringUtils.isEmpty(email) || StringUtils.isEmpty(imageCodeKey) || StringUtils.isEmpty(imageCodeValue)){
            throw new BusinessException("请填写参数");
        }
        //校验手机号是否已经被注册 ?
        User userp = userMapper.loadByPhone(phone);
        User usere = userMapper.loadByEmail(email);
        if (userp != null || usere != null){
            throw new BusinessException("用户已存在请直接登录");
        }
        //根据图形验证码的key查询redis中的值
        Object imageCodeValueTmp = redisTemplate.opsForValue().get(imageCodeKey);
        if (imageCodeValueTmp == null){
            throw  new BusinessException("图形验证码已经失效请点击重写获取");
        }
        if (!imageCodeValueTmp.toString().equalsIgnoreCase(imageCodeValue)){
            throw  new BusinessException("请填写正确的图形验证码值");
        }
        String smCodeKey = BaseConstants.VerifyCodeConstants.BUSINESS_REGISTER_PREFIX + email;
        Object smCodeValueTmp = redisTemplate.opsForValue().get(smCodeKey);
        if (smCodeValueTmp != null){
            //获取smsCodeValue=随机数 + 时间戳，截取时间戳
            Long oldTime = Long.valueOf(smCodeValueTmp.toString().split(":")[1]);
            if (System.currentTimeMillis() - oldTime <= 1*60*1000){
                throw new BusinessException("请不要恶意调用接口");
            }
            //未超时
            smCode = smCodeValueTmp.toString().split(":")[0];//随机数
        } else {
            //获取不到 说明已经过期，直接生成新的验证码
            smCode = StrUtils.getComplexRandomString(4);
        }
        String smsCodeValue = smCode + ":" + System.currentTimeMillis();//随机数加时间戳
        redisTemplate.opsForValue().set(smCodeKey,smsCodeValue,3,TimeUnit.MINUTES);
        //6.发送短信验证码
        //EmailUtil.e
        System.out.println("亲，您的验证码是：" + smCode + "。请在3分钟内使用！！");
    }

}
